// 版权声明，Epic Games 公司保留所有权利

#include "LyraInventoryManagerComponent.h"

#include "Engine/ActorChannel.h"
#include "Engine/World.h"
#include "GameFramework/GameplayMessageSubsystem.h"
#include "LyraInventoryItemDefinition.h"
#include "LyraInventoryItemInstance.h"
#include "NativeGameplayTags.h"
#include "Net/UnrealNetwork.h"

#include UE_INLINE_GENERATED_CPP_BY_NAME(LyraInventoryManagerComponent)

class FLifetimeProperty;
struct FReplicationFlags;

UE_DEFINE_GAMEPLAY_TAG_STATIC(TAG_Lyra_Inventory_Message_StackChanged, "Lyra.Inventory.Message.StackChanged"); // 定义库存堆栈变化消息标签

//////////////////////////////////////////////////////////////////////
// FLyraInventoryEntry

/**
 * 获取调试字符串
 * @return 调试字符串
 */
FString FLyraInventoryEntry::GetDebugString() const
{
	TSubclassOf<ULyraInventoryItemDefinition> ItemDef;
	if (Instance != nullptr)
	{
		ItemDef = Instance->GetItemDef(); // 获取物品定义类
	}

	return FString::Printf(TEXT("%s (%d x %s)"), *GetNameSafe(Instance), StackCount, *GetNameSafe(ItemDef)); // 返回格式化字符串
}

//////////////////////////////////////////////////////////////////////
// FLyraInventoryList

/**
 * 复制移除前调用
 * @param RemovedIndices 移除的索引数组视图
 * @param FinalSize 最终大小
 */
void FLyraInventoryList::PreReplicatedRemove(const TArrayView<int32> RemovedIndices, int32 FinalSize)
{
	for (int32 Index : RemovedIndices)
	{
		FLyraInventoryEntry& Stack = Entries[Index];
		BroadcastChangeMessage(Stack, /*OldCount=*/ Stack.StackCount, /*NewCount=*/ 0); // 广播变化消息
		Stack.LastObservedCount = 0; // 重置最后观察到的数量
	}
}

/**
 * 复制添加后调用
 * @param AddedIndices 添加的索引数组视图
 * @param FinalSize 最终大小
 */
void FLyraInventoryList::PostReplicatedAdd(const TArrayView<int32> AddedIndices, int32 FinalSize)
{
	for (int32 Index : AddedIndices)
	{
		FLyraInventoryEntry& Stack = Entries[Index];
		BroadcastChangeMessage(Stack, /*OldCount=*/ 0, /*NewCount=*/ Stack.StackCount); // 广播变化消息
		Stack.LastObservedCount = Stack.StackCount; // 更新最后观察到的数量
	}
}

/**
 * 复制变化后调用
 * @param ChangedIndices 变化的索引数组视图
 * @param FinalSize 最终大小
 */
void FLyraInventoryList::PostReplicatedChange(const TArrayView<int32> ChangedIndices, int32 FinalSize)
{
	for (int32 Index : ChangedIndices)
	{
		FLyraInventoryEntry& Stack = Entries[Index];
		check(Stack.LastObservedCount != INDEX_NONE); // 检查最后观察到的数量是否有效
		BroadcastChangeMessage(Stack, /*OldCount=*/ Stack.LastObservedCount, /*NewCount=*/ Stack.StackCount); // 广播变化消息
		Stack.LastObservedCount = Stack.StackCount; // 更新最后观察到的数量
	}
}

/**
 * 广播变化消息
 * @param Entry 库存条目
 * @param OldCount 旧数量
 * @param NewCount 新数量
 */
void FLyraInventoryList::BroadcastChangeMessage(FLyraInventoryEntry& Entry, int32 OldCount, int32 NewCount)
{
	FLyraInventoryChangeMessage Message;
	Message.InventoryOwner = OwnerComponent; // 设置库存拥有者
	Message.Instance = Entry.Instance; // 设置物品实例
	Message.NewCount = NewCount; // 设置新数量
	Message.Delta = NewCount - OldCount; // 设置变化量

	UGameplayMessageSubsystem& MessageSystem = UGameplayMessageSubsystem::Get(OwnerComponent->GetWorld()); // 获取消息子系统
	MessageSystem.BroadcastMessage(TAG_Lyra_Inventory_Message_StackChanged, Message); // 广播消息
}

/**
 * 添加条目（通过物品定义类）
 * @param ItemDef 物品定义类
 * @param StackCount 堆叠数量
 * @return 创建的物品实例
 */
ULyraInventoryItemInstance* FLyraInventoryList::AddEntry(TSubclassOf<ULyraInventoryItemDefinition> ItemDef, int32 StackCount)
{
	ULyraInventoryItemInstance* Result = nullptr;

	check(ItemDef != nullptr); // 检查物品定义类是否有效
 	check(OwnerComponent); // 检查拥有者组件是否有效

	AActor* OwningActor = OwnerComponent->GetOwner(); // 获取拥有者Actor
	check(OwningActor->HasAuthority()); // 检查是否具有权限

	FLyraInventoryEntry& NewEntry = Entries.AddDefaulted_GetRef(); // 添加默认条目
	NewEntry.Instance = NewObject<ULyraInventoryItemInstance>(OwnerComponent->GetOwner());  //@TODO: 由于UE-127172，使用Actor而不是组件作为外部对象
	NewEntry.Instance->SetItemDef(ItemDef); // 设置物品定义类
	// 遍历物品定义的片段
	for (ULyraInventoryItemFragment* Fragment : GetDefault<ULyraInventoryItemDefinition>(ItemDef)->Fragments)
	{
		if (Fragment != nullptr)
		{
			Fragment->OnInstanceCreated(NewEntry.Instance); // 调用片段实例创建回调
		}
	}
	NewEntry.StackCount = StackCount; // 设置堆叠数量
	Result = NewEntry.Instance; // 设置返回值

	//const ULyraInventoryItemDefinition* ItemCDO = GetDefault<ULyraInventoryItemDefinition>(ItemDef);
	MarkItemDirty(NewEntry); // 标记条目为脏

	return Result; // 返回创建的实例
}

/**
 * 添加条目（通过物品实例）
 * @param Instance 物品实例
 */
void FLyraInventoryList::AddEntry(ULyraInventoryItemInstance* Instance)
{
	unimplemented(); // 未实现
}

/**
 * 移除条目
 * @param Instance 物品实例
 */
void FLyraInventoryList::RemoveEntry(ULyraInventoryItemInstance* Instance)
{
	for (auto EntryIt = Entries.CreateIterator(); EntryIt; ++EntryIt)
	{
		FLyraInventoryEntry& Entry = *EntryIt;
		if (Entry.Instance == Instance)
		{
			EntryIt.RemoveCurrent(); // 移除当前条目
			MarkArrayDirty(); // 标记数组为脏
		}
	}
}

/**
 * 获取所有物品
 * @return 物品实例数组
 */
TArray<ULyraInventoryItemInstance*> FLyraInventoryList::GetAllItems() const
{
	TArray<ULyraInventoryItemInstance*> Results;
	Results.Reserve(Entries.Num()); // 预分配空间
	for (const FLyraInventoryEntry& Entry : Entries)
	{
		if (Entry.Instance != nullptr) //@TODO: 更希望不在这里处理这个问题，而是进一步隐藏它？
		{
			Results.Add(Entry.Instance); // 添加物品实例
		}
	}
	return Results; // 返回结果数组
}

//////////////////////////////////////////////////////////////////////
// ULyraInventoryManagerComponent

/**
 * 构造函数
 * @param ObjectInitializer 对象初始化器
 */
ULyraInventoryManagerComponent::ULyraInventoryManagerComponent(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
	, InventoryList(this) // 初始化库存列表
{
	SetIsReplicatedByDefault(true); // 默认启用复制
}

/**
 * 获取生命周期复制属性
 * @param OutLifetimeProps 输出生命周期属性数组
 */
void ULyraInventoryManagerComponent::GetLifetimeReplicatedProps(TArray< FLifetimeProperty >& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps); // 调用父类方法

	DOREPLIFETIME(ThisClass, InventoryList); // 复制库存列表
}

/**
 * 检查是否可以添加物品定义
 * @param ItemDef 物品定义类
 * @param StackCount 堆叠数量
 * @return 是否可以添加
 */
bool ULyraInventoryManagerComponent::CanAddItemDefinition(TSubclassOf<ULyraInventoryItemDefinition> ItemDef, int32 StackCount)
{
	//@TODO: 添加对堆叠限制/唯一性检查等的支持
	return true; // 暂时总是返回true
}

/**
 * 添加物品定义
 * @param ItemDef 物品定义类
 * @param StackCount 堆叠数量
 * @return 创建的物品实例
 */
ULyraInventoryItemInstance* ULyraInventoryManagerComponent::AddItemDefinition(TSubclassOf<ULyraInventoryItemDefinition> ItemDef, int32 StackCount)
{
	ULyraInventoryItemInstance* Result = nullptr;
	if (ItemDef != nullptr)
	{
		Result = InventoryList.AddEntry(ItemDef, StackCount); // 添加条目
		
		// 如果使用注册子对象列表且准备好复制且结果有效
		if (IsUsingRegisteredSubObjectList() && IsReadyForReplication() && Result)
		{
			AddReplicatedSubObject(Result); // 添加复制子对象
		}
	}
	return Result; // 返回结果
}

/**
 * 添加物品实例
 * @param ItemInstance 物品实例
 */
void ULyraInventoryManagerComponent::AddItemInstance(ULyraInventoryItemInstance* ItemInstance)
{
	InventoryList.AddEntry(ItemInstance); // 添加条目
	// 如果使用注册子对象列表且准备好复制且物品实例有效
	if (IsUsingRegisteredSubObjectList() && IsReadyForReplication() && ItemInstance)
	{
		AddReplicatedSubObject(ItemInstance); // 添加复制子对象
	}
}

/**
 * 移除物品实例
 * @param ItemInstance 物品实例
 */
void ULyraInventoryManagerComponent::RemoveItemInstance(ULyraInventoryItemInstance* ItemInstance)
{
	InventoryList.RemoveEntry(ItemInstance); // 移除条目

	if (ItemInstance && IsUsingRegisteredSubObjectList())
	{
		RemoveReplicatedSubObject(ItemInstance); // 移除复制子对象
	}
}

/**
 * 获取所有物品
 * @return 物品实例数组
 */
TArray<ULyraInventoryItemInstance*> ULyraInventoryManagerComponent::GetAllItems() const
{
	return InventoryList.GetAllItems(); // 返回所有物品
}

/**
 * 根据定义查找第一个物品堆栈
 * @param ItemDef 物品定义类
 * @return 找到的物品实例
 */
ULyraInventoryItemInstance* ULyraInventoryManagerComponent::FindFirstItemStackByDefinition(TSubclassOf<ULyraInventoryItemDefinition> ItemDef) const
{
	for (const FLyraInventoryEntry& Entry : InventoryList.Entries)
	{
		ULyraInventoryItemInstance* Instance = Entry.Instance;

		if (IsValid(Instance))
		{
			if (Instance->GetItemDef() == ItemDef)
			{
				return Instance; // 返回找到的实例
			}
		}
	}

	return nullptr; // 未找到返回nullptr
}

/**
 * 根据定义获取物品总数量
 * @param ItemDef 物品定义类
 * @return 总数量
 */
int32 ULyraInventoryManagerComponent::GetTotalItemCountByDefinition(TSubclassOf<ULyraInventoryItemDefinition> ItemDef) const
{
	int32 TotalCount = 0;
	for (const FLyraInventoryEntry& Entry : InventoryList.Entries)
	{
		ULyraInventoryItemInstance* Instance = Entry.Instance;

		if (IsValid(Instance))
		{
			if (Instance->GetItemDef() == ItemDef)
			{
				++TotalCount; // 增加计数
			}
		}
	}

	return TotalCount; // 返回总数量
}

/**
 * 根据定义消耗物品
 * @param ItemDef 物品定义类
 * @param NumToConsume 要消耗的数量
 * @return 是否成功消耗
 */
bool ULyraInventoryManagerComponent::ConsumeItemsByDefinition(TSubclassOf<ULyraInventoryItemDefinition> ItemDef, int32 NumToConsume)
{
	AActor* OwningActor = GetOwner(); // 获取拥有者Actor
	if (!OwningActor || !OwningActor->HasAuthority())
	{
		return false; // 无权限返回false
	}

	//@TODO: 目前是N平方复杂度，因为没有加速结构
	int32 TotalConsumed = 0;
	while (TotalConsumed < NumToConsume)
	{
		if (ULyraInventoryItemInstance* Instance = ULyraInventoryManagerComponent::FindFirstItemStackByDefinition(ItemDef))
		{
			InventoryList.RemoveEntry(Instance); // 移除条目
			++TotalConsumed; // 增加已消耗计数
		}
		else
		{
			return false; // 找不到物品返回false
		}
	}

	return TotalConsumed == NumToConsume; // 返回是否完全消耗
}

/**
 * 准备复制
 */
void ULyraInventoryManagerComponent::ReadyForReplication()
{
	Super::ReadyForReplication(); // 调用父类方法

	// 注册现有的ULyraInventoryItemInstance
	if (IsUsingRegisteredSubObjectList())
	{
		for (const FLyraInventoryEntry& Entry : InventoryList.Entries)
		{
			ULyraInventoryItemInstance* Instance = Entry.Instance;

			if (IsValid(Instance))
			{
				AddReplicatedSubObject(Instance); // 添加复制子对象
			}
		}
	}
}

/**
 * 复制子对象
 * @param Channel Actor通道
 * @param Bunch 输出数据包
 * @param RepFlags 复制标志
 * @return 是否写入了数据
 */
bool ULyraInventoryManagerComponent::ReplicateSubobjects(UActorChannel* Channel, class FOutBunch* Bunch, FReplicationFlags* RepFlags)
{
	bool WroteSomething = Super::ReplicateSubobjects(Channel, Bunch, RepFlags); // 调用父类方法

	// 复制所有物品实例
	for (FLyraInventoryEntry& Entry : InventoryList.Entries)
	{
		ULyraInventoryItemInstance* Instance = Entry.Instance;

		if (Instance && IsValid(Instance))
		{
			WroteSomething |= Channel->ReplicateSubobject(Instance, *Bunch, *RepFlags); // 复制子对象
		}
	}

	return WroteSomething; // 返回是否写入了数据
}

//////////////////////////////////////////////////////////////////////
//
// 注释掉的库存过滤器相关代码
// UCLASS(Abstract)
// class ULyraInventoryFilter : public UObject
// {
// public:
// 	virtual bool PassesFilter(ULyraInventoryItemInstance* Instance) const { return true; }
// };
// 
// UCLASS()
// class ULyraInventoryFilter_HasTag : public ULyraInventoryFilter
// {
// public:
// 	virtual bool PassesFilter(ULyraInventoryItemInstance* Instance) const { return true; }
// };